/*
 * Created by Storm Zhang, Feb 11, 2014.
 */

package com.oazon.common.util;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.ActivityManager;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.Request.Method;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.moco.launcher.bean.MocoAttribute;
import com.moco.launcher.bean.MocoItemInfo;
import com.moco.launcher.http.HttpUtil;
import com.moco.launcher.listener.CloudErrorListener;
import com.moco.launcher.listener.CloudJsonResponseListener;
import com.moco.launcher.listener.CloudListener;
import com.moco.launcher.listener.CloudStringResponseListener;
import com.oazon.common.Logger;
import com.oazon.moco.lan.util.UrlDecode;
import com.oazon.moco.link.core.LinkSDK;
import com.oazon.moco.playlist.bean.AbstractMedia;
import com.oazon.moco.playlist.bean.ItemType;
import com.oazon.moco.playlist.bean.MediaCollection;
import com.oazon.moco.playlist.bean.MediaCollectionBean;
import com.oazon.moco.playlist.bean.MediaMetadata;
import com.oazon.moco.playlist.bean.MediaMetadataBean;
import com.oazon.moco.playlist.db.MediaCollectionDao;
import com.oazon.moco.playlist.db.MediaMetadataDao;
import com.oazon.moco.playlist.db.PlaylistDao;
import com.oazon.sonos.bean.GetMetadataResponse;

/**
 * 网络请求，uri拼接
 * 
 * @author Gavin
 *
 */
public class RequestManager {

	private static final String TAG = "RequestManager";
	private static RequestQueue mRequestQueue;
	private static ImageLoader mImageLoader;

	private static Context context;

	private static MediaCollectionDao collectionDao;
	private static MediaMetadataDao mediaMetadataDao;
	private static HashMap<String, Object> CACHE_MAP = new HashMap<String, Object>();

	private RequestManager() {
		// no instances
	}

	public static void init(Context context) {
		RequestManager.context = context;
		mRequestQueue = Volley.newRequestQueue(context);

		int memClass = ((ActivityManager) context
				.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
		// Use 1/8th of the available memory for this memory cache.
		int cacheSize = 1024 * 1024 * memClass / 8;
		mImageLoader = new ImageLoader(mRequestQueue, new BitmapLruCache(
				cacheSize));

		collectionDao = new MediaCollectionDao(context);
		mediaMetadataDao = new MediaMetadataDao(context);
	}

	public static RequestQueue getRequestQueue() {
		if (mRequestQueue != null) {
			return mRequestQueue;
		} else {
			throw new IllegalStateException("RequestQueue not initialized");
		}
	}

	public static void addRequest(Request<?> request, Object tag) {
		if (tag != null) {
			request.setTag(tag);
		}
		mRequestQueue.add(request);
	}

	public static void cancelAll(Object tag) {
		mRequestQueue.cancelAll(tag);
	}

	/**
	 * Returns instance of ImageLoader initialized with {@see FakeImageCache}
	 * which effectively means that no memory caching is used. This is useful
	 * for images that you know that will be show only once.
	 * 
	 * @return
	 */
	public static ImageLoader getImageLoader() {
		if (mImageLoader != null) {
			return mImageLoader;
		} else {
			throw new IllegalStateException("ImageLoader not initialized");
		}
	}

	public static Response.Listener<JSONObject> responseJsonListener(
			CloudListener l) {
		return new CloudJsonResponseListener(l);
	}

	public static Response.Listener<String> responseListener(CloudListener l) {
		return new CloudStringResponseListener(l);
	}

	private static Response.ErrorListener errorListener(CloudListener l) {
		return new CloudErrorListener(l);
	}

	public static void sendpost(Context ctx, String url, final CloudListener l) {
		try {
			//if(!Utils.hasNetwork(context)){
			if(!Utils.isWifiConnectedOrConnecting(context)){
				Toast.makeText(context, "WiFi未连接", Toast.LENGTH_SHORT).show();
			}
			StringRequest req = new StringRequest(Method.POST, url,
					responseListener(l), errorListener(l)){
				@Override
				public Map<String, String> getHeaders()
						throws AuthFailureError {
					Map<String, String> headers = new HashMap<String, String>();
					headers.put("deviceId", LinkSDK.UUID);
					return headers;
				}
			};
			req.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 0, 1.0f));//20s-->8s
			RequestManager.addRequest(req, ctx);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static void sendRequest(Context ctx, String url,
			final CloudListener l) {
		try {
			//if(!Utils.hasNetwork(context)){
			if(!Utils.isWifiConnectedOrConnecting(context)){	
			Toast.makeText(context, "WiFi未连接", Toast.LENGTH_SHORT).show();
			}
			Log.d(TAG, "request " + url);
			StringRequest req = new StringRequest(Method.GET, url,
					responseListener(l), errorListener(l)){
				@Override
				public Map<String, String> getHeaders()
						throws AuthFailureError {
					Map<String, String> headers = new HashMap<String, String>();
					headers.put("deviceId", LinkSDK.UUID);
					return headers;
				}
			};
			req.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 0, 1.0f));
			RequestManager.addRequest(req, ctx);
		} catch (Exception e) {
			Logger.d(TAG , "sendRequest error:"+e.getMessage());
		}

	}

	public static void getListByAsync(Context ctx, String url,
			final CloudListener l) {
		HttpUtil.getClient().setTimeout(10000);
		HttpUtil.getClient().get(url, new AsyncHttpResponseHandler() {

			@Override
			public void onFailure(int arg0, Header[] arg1, byte[] arg2,
					Throwable arg3) {
			}

			@Override
			public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
				String str = new String(arg2);
				Log.d(TAG, "getListByAsync STR= \n" + str);
			}

		});
	}

	public static void getListByHttpClient(Context ctx, String url,
			final CloudListener l) {
		final String _url = url;
		final Context _ctx = ctx;
		Runnable r = new Runnable() {
			@Override
			public void run() {
				String result = null;
				try {
					result = HttpUtil.getByHttpClient(_ctx, _url);
				} catch (Exception e) {
					e.printStackTrace();
				}
				Log.d(TAG, "RESULT=\n " + result);
			}

		};

		Thread t = new Thread(r);
		t.start();
	}

	public static void parseJsonResponse(String response,
			List<MocoItemInfo> mItems) {
		mItems.clear();
		try {
			JSONArray array = new JSONArray(response);
			Log.d(TAG, "array.length()=" + array.length());
			for (int i = 0; i < array.length(); i++) {
				JSONObject obj = (JSONObject) array.get(i);
				MocoItemInfo info = new MocoItemInfo();

				JSONObject obj_item = (JSONObject) obj.get("item");

				// info.setCreateTime(obj_item.getString("createTime"));
				// info.setDesc(obj_item.getString("shortDesc"));
				info.setId(obj_item.getString("id"));
				info.setPicture(obj_item.getString("picture"));
				// info.setSortId(obj_item.getInt("sortId"));
				info.setTitle(obj_item.getString("title"));
				// info.setSource(obj_item.getString("source"));
				// info.setSourceId(obj_item.getString("sourceId"));
				info.setType(obj_item.getString("type"));
				// info.setSourceType(obj_item.getString("sourceType"));
				// info.setUpdateTime(obj_item.getString("updateTime"));
				info.setUrl(obj_item.getString("url"));
				Log.d(TAG, "array.url()=" + info.getUrl());
				JSONArray obj_attrs = (JSONArray) obj.get("attributes");
				for (int j = 0; j < obj_attrs.length(); j++) {
					MocoAttribute attr = new MocoAttribute();
					JSONObject obj_attr = (JSONObject) obj_attrs.get(j);
					attr.setAttrId(obj_attr.getString("attributeId"));
					attr.setAttrName(obj_attr.getString("attributeName"));
					attr.setAttrValue(obj_attr.getString("attributeValue"));
					attr.setCreateTime(obj_attr.getString("createTime"));
					attr.setId(obj_attr.getString("id"));
					attr.setItemId(obj_attr.getString("itemId"));
					attr.setUpdateTime(obj_attr.getString("updateTime"));
					info.mAttrs.add(attr);
				}
				info.getArtist();
				info.getLyric();
				mItems.add(info);
			}
		} catch (JSONException e) {
			Log.d(TAG, "passUrl catch error" + e.getCause());
			e.printStackTrace();
		}
	}

	public static GetMetadataResponse<AbstractMedia> parseJsonResponse(
			String response) {

		if (StringUtils.isBlank(response)) {
			Log.e(TAG, "==parseJsonResponse response is null");
			return null;
		}

		if(response.startsWith("{\"searchResult\"")){
			response = StringUtils.replace(response, "{\"searchResult\"", "{\"getMetadataResult\"", 1);
		}
		
		GetMetadataResponse<AbstractMedia> metadataResult = null;
		try {
			metadataResult = JSON.parseObject(response,
					new TypeReference<GetMetadataResponse<MediaCollection>>() {
					}.getType());

			if (metadataResult.getGetMetadataResult()
					.getMediaCollectionOrMediaMetadata().get(0).getItemType()
					.equals(ItemType.TRACK)) {
				metadataResult = JSON.parseObject(response,
						new TypeReference<GetMetadataResponse<MediaMetadata>>() {
						}.getType());
			}
		} catch (Exception e) {
			Log.e(TAG, "==parseJsonResponse==" + response);
			return null;
		}

		Log.d(TAG, "==parseJsonResponse success");
		return metadataResult;
	}

	public static String spliceUri(String id, String url) {
		String[] ids = url.split("id=");
		String[] idss = ids[1].split("&");
		if (idss.length >= 2) {
			url = ids[0] + "id=" + id + "&";
			for (int i = 1; i < idss.length; i++) {
				url += idss[i] + "&";
			}
		} else {
			url = ids[0] + "id=" + id + "&";
		}
		return url;
	}

	public static Map<String, String> paseResURI(String resID) {

		if (resID == null) {
			return null;
		}
		String[] sids = resID.split("[?]sid=");
		String[] params = sids[0].split("[:]");

		Map<String, String> paramsMap = new HashMap<String, String>();
		String itemID = "";

		for (int i = 1; i < params.length; i++) {
			if (i == params.length - 1) {
				itemID += params[i];
			} else {
				itemID += params[i] + ":";
			}
		}
		paramsMap.put("id", itemID);
		try {
			if (sids[1] != null && !"null".equals(sids[1])) {
				paramsMap.put("provider", sids[1]);
			}
		} catch (Exception e) {
		}
		return paramsMap;
	}

	public static String getProvide(String url) {
		Map<String, String> urlParams = new HashMap<String, String>();
		UrlDecode.parseParameters(urlParams, url, null);
		return urlParams.get("provider");
	}

	public static String spliceUri(Map<String, String> params, String url,
			String encode) {

		Map<String, String> urlParams = new HashMap<String, String>();
		UrlDecode.parseParameters(urlParams, url, encode);

		if (!StringUtils.isEmpty(params.get("id"))) {
			urlParams.put("id", params.get("id"));
		}
		if (!StringUtils.isEmpty(params.get("index"))) {
			urlParams.put("index", params.get("index"));
		}
		if (!StringUtils.isEmpty(params.get("count"))) {
			urlParams.put("count", params.get("count"));
		}
		if (!StringUtils.isEmpty(params.get("recursive"))) {
			urlParams.put("recursive", params.get("recursive"));
		}
		if (!StringUtils.isEmpty(params.get("provider"))) {
			urlParams.put("provider", params.get("provider"));
		}
		url = UrlDecode.getUrl(urlParams, url, encode);
		return url;
	}


	@SuppressWarnings("unchecked")
	public static List<MediaMetadataBean> requsetMediaMetadataBean(
			String parentId, String provider) {
		
		if(provider == null){
			provider ="";
		}
		if(parentId == null){
			return null;
		}
		
		String key = parentId + "-" + provider + "-MediaMetadata";
		if (CACHE_MAP.get(key) != null) {
			return (List<MediaMetadataBean>)CACHE_MAP.get(key);
		} else {
			List<MediaMetadataBean> result = mediaMetadataDao.selectByParentId(parentId, provider);
			if(result != null && result.size() > 0)
				CACHE_MAP.put(key, result);
			return result;
		}

	}
	
	public static List<MediaCollectionBean> requsetMediaCollectionBean(
			String parentId, String provider) {
		
		if(provider == null){
			provider ="";
		}
		if(parentId == null){
			return null;
		}
		String key = parentId + "-" + provider + "-MediaCollection";
		if (CACHE_MAP.get(key) != null) {
			return (List<MediaCollectionBean>)CACHE_MAP.get(key);
		} else {
			List<MediaCollectionBean> result = collectionDao.selectByParentId(parentId, provider);
			if(result != null && result.size() > 0)
				CACHE_MAP.put(key, result);
			return result;
		}
	}
	
	public static void insertListMediaCollection(List<MediaCollectionBean> collectionBeans){
		collectionDao.insertListMediaCollection(collectionBeans);
	}

	public static void insertListMediaMetadata(List<MediaMetadataBean> mediaMetadataBeans){
		mediaMetadataDao.insertListMediaMetadata(mediaMetadataBeans);
	}
	
	public static void deleteByParentId(String parentId, String provider) {
		collectionDao.deleteByParentId(parentId, provider);	
		mediaMetadataDao.deleteByParentId(parentId, provider);
		CACHE_MAP.clear();
	}
	
	public static void deleteByProvider(String provider){
		collectionDao.deleteByProvider(provider);	
		mediaMetadataDao.deleteByProvider(provider);
		CACHE_MAP.clear();
	}
	
	static Map<String, String> param = new HashMap<String, String>();
	public static void post_o2_songlist(String url,String provider,String str) {
	
		param.put("provider", provider);
		param.put("mediaMetadatas", str);
		
		StringRequest request = new StringRequest(Method.POST,url, new Response.Listener<String>() {

			@Override
			public void onResponse(String arg0) {
				Logger.d(TAG, "Response=="+arg0);
			}
		}, new Response.ErrorListener() {

			@Override
			public void onErrorResponse(VolleyError arg0) {
				Log.d(TAG, arg0.getMessage());
				
			}
		}){
			@Override
			protected Map<String, String> getParams()
					throws AuthFailureError {
				return param;
			}
		};
		
		mRequestQueue.add(request);
	}
}
